﻿; (function (global) {

    'use strict';

    global.Strategies = global.Strategies || {};

    Strategies.HiddenSingle = function HiddenSingle() {
        this.type = 'filler';
    }


    Strategies.HiddenSingle.prototype.perform = function (grid) {
        var performedCell = this.performOn(grid, grid.cells);
        if (performedCell) {
            return { cell: performedCell, deduction: 'row' };
        }

        performedCell = this.performOn(grid, grid.cellsByColumn);
        if (performedCell) {
            return { cell: performedCell, deduction: 'column' };
        }

        performedCell = this.performOn(grid, grid.cellsByRegion);
        if (performedCell) {
            return { cell: performedCell, deduction: 'region' };
        }

        return null;
    }

    Strategies.HiddenSingle.prototype.performOn = function (grid, cellsArray) {

        for (var i = 0; i < 9; i++) {
            var cells = cellsArray[i];

            var performedCell = this.performOnCellGroup(grid, cells);
            if (performedCell) {
                return performedCell;
            }
        }

        return null;
    }

    Strategies.HiddenSingle.prototype.performOnCellGroup = function (grid, cells) {

        var found = this.findInCells(cells);
        if (found) {
            found.cell.setValue(found.value);
            SolvingHelper.removeDependingCandidates(found.cell, grid);
            // console.log("hidden single", found.value, found.cell);
            return found.cell;
        }

        return null;
    }

    // do not try to optimise for minor empty cells, this technique won't be helpfull any way in this case
    Strategies.HiddenSingle.prototype.findInCells = function (cells) {
        for (var k = 1; k < 10; k++) {
            var occurences = 0;
            var cellForValue = null;
            for (var i = 0, len = cells.length; i < len; i++) {
                var cell = cells[i];
                if (cell.value > 0)
                    continue;

                if (cell.candidates.has[k]) {
                    occurences++;
                    cellForValue = cell;
                }

                if (occurences > 1)
                    break;
            }

            if (occurences === 1) {
                return { value: k, cell: cellForValue }
            }
        }

        return null;
    }

    Strategies.HiddenSingle.prototype.findInCellsAlt = function (cells) {

        var emptyCells = SolvingHelper.getEmptyCells(cells)
        var distinctCandidates = SolvingHelper.getDistinctCandidates(emptyCells);

        for (var p = 0, l = distinctCandidates.length; p < l; p++) {
            var k = distinctCandidates[p];
            var occurences = 0;
            var cellForValue = null;
            for (var i = 0, len = emptyCells.length; i < len; i++) {
                var cell = emptyCells[i];

                if (cell.candidates.has[k]) {
                    occurences++;
                    cellForValue = cell;
                }

                if (occurences > 1)
                    break;
            }

            if (occurences === 1) {
                return { value: k, cell: cellForValue }
            }
        }

        return null;


    }

}(this));
